#ifndef _TEXTOUTPUT_H_
#define _TEXTOUTPUT_H_

#pragma once
#include "../stdafx.h"

#include <vector>
#include <deque>

#define FONTLIST_SZ 256

using namespace std;

class CFontEntry
{
public:
	GLuint list_base;
	int font_height;
	int font_width;
	char *font_name;
	CFontEntry():list_base(0), font_height(0), font_name(NULL){}
	CFontEntry(GLuint base, int height, char *name):list_base(base), font_height(height), font_name(name){}
	~CFontEntry(){delete font_name;}
	void activate(void) const {glListBase(list_base);}
};

class CFontManager// : public CSingleton<CFontManager>
{
private:
	vector <CFontEntry* > _fonts;
	CFontEntry* _buildFont(const char* fontName, int height)
	{
		GLuint b = 0;
		HFONT font = NULL;
		HDC hDC = NULL;
		if (!(hDC = GetDC(NULL)))
			return NULL;
		if (!(b = glGenLists(FONTLIST_SZ)))
			goto error1;

		if (!(font = CreateFontA( -height,
			0,
			0,
			0,
			FW_BOLD,
			FALSE,
			FALSE,
			FALSE,
			ANSI_CHARSET,
			OUT_TT_PRECIS,
			CLIP_DEFAULT_PRECIS,
			ANTIALIASED_QUALITY,
			FF_DONTCARE|DEFAULT_PITCH,
			fontName)))
			goto error2;

		SelectObject(hDC, font);
		wglUseFontBitmaps(hDC, 0, FONTLIST_SZ, b);

		TEXTMETRIC metrics;
		if (GetTextMetrics(hDC, &metrics) == 0)
			goto error21;

		ReleaseDC(NULL, hDC);
		DeleteObject(font);

		const size_t sz = strlen(fontName);
		char * name = new char[sz];
		if (!name)
			goto error2;
		;
		CFontEntry *fe = new CFontEntry(b, height, strcpy(name, fontName));
		if (!fe)
			goto error3;
		fe->font_width = (int)(metrics.tmAveCharWidth);
		_fonts.push_back(fe);
		return fe;
error3:
		delete name;
error21:
		DeleteObject(font);
error2:
		glDeleteLists(b, FONTLIST_SZ);
error1:
		ReleaseDC(NULL, hDC);
		return NULL;
	};
	static CFontManager * _inst;

	CFontManager(){setupFont("Verdana", 12);}
	~CFontManager(){}
public:
	static CFontManager * get()
	{
		if (!_inst)
			_inst = new CFontManager();
		return _inst;
	}
	const CFontEntry* setupFont(const char* fontName, int height)
	{
		for(vector<CFontEntry*>::iterator it = _fonts.begin(); it != _fonts.end(); it++)
		{
			CFontEntry *f = *it;
			if (f->font_height == height && !_stricmp(f->font_name, fontName))
				return f;
		}
		return _buildFont(fontName, height);
	}

	void deleteFont(CFontEntry* font)
	{
		for (vector<CFontEntry*>::iterator it = _fonts.begin(); it != _fonts.end(); it++)
		{
			if (*it == font)
				_fonts.erase(it);
		}
		delete font;
	}
	const CFontEntry * getDefaultFont(){return *(_fonts.begin());}
	void ActivateFont(const CFontEntry* font = NULL)
	{
		const CFontEntry* fe = (font != NULL) ? font : *(_fonts.begin());
		glListBase(fe->list_base);
	}

//	static void print_line_at(char* str, size_t sz_text, int x, int y);
	static void print_line_at(char* str, size_t sz_text, float fx, float fy);
	static void print_line_at(char* str, size_t sz_text, float fx, float fy, float fz);
};

#endif // _TEXTOUTPUT_H_